﻿#include "Tests.h"
#include "Metric.h"


#define PI 3.1415926535897932384626433832795

Multivector convert(Multivector& a, mat space);

void Tests::run()
{
	//Test reffering to outer product
	{
		//(e1 + e2) ^ (e3 ^ e2)
		Multivector a = Multivector();
		a(1) = 1;
		a(2) = 1;
		//a.print();

		Multivector b = Multivector();
		b(4) = 1;
		b(2) = 1;
		//b.print();

		Multivector c = a ^ b;
		//c.print();

		//e1 ∧ e2 + e1 ∧ e3 + e2 ∧ e3
		assert(c(3) == 1);
		assert(c(5) == 1);
		assert(c(6) == 1);
	}

	//Test reffering to outer product
	{
		//(e2 +e3) ∧ ( 1/2 e1 +e2 + 3/2 e3)
		Multivector a = Multivector();
		a(2) = 1;
		a(4) = 1;

		//a.print();

		Multivector b = Multivector();
		b(1) = 0.5;
		b(2) = 1;
		b(4) = 1.5;
		//b.print();

		Multivector c = a ^ b;

		//c.print();

		assert(c(3) == -0.5);
		assert(c(5) == -0.5);
		assert(c(6) == 0.5);
	}

	//Test reffering to outer product
	//Showing another way to initialize the Multivector
	{
		//(e2 + e3) ∧ ( 1/2 e1 +e2 + 3/2 e3)
		Multivector e2 = Multivector(2);
		Multivector e3 = Multivector(4);

		Multivector e1 = Multivector(1);
		//b.print();

		Multivector c = (e2 + e3) ^ ( (0.5)*e1 + e2 + (1.5)*e3);

		//c.print();

		assert(c(3) == -0.5);
		assert(c(5) == -0.5);
		assert(c(6) == 0.5);
	}

	//Test reffering to outer product
	{

		//(4e1 +e2 +e3) ∧ (3e1)
		Multivector a = Multivector();
		a(1) = 4;
		a(2) = 1;
		a(4) = 1;
		//a.print();

		Multivector b = Multivector();
		b(1) = 3;
		//b.print();

		Multivector c = a ^ b;

		//−3e1 ∧ e2 − 3e1 ∧ e3
		assert(c(3) == -3);
		assert(c(5) == -3);

		//c.print();
	}

	//(e1 +e2) ∧ (e2 ∧ e1 +e3 ∧ e2)

	//Test reffering to outer product
	{
		//(e1 +e2) ∧ (e2 ∧ e1 +e3 ∧ e2)
		Multivector e1 = Multivector(1);
		Multivector e2 = Multivector(2);
		Multivector e3 = Multivector(4);


		Multivector c = (e1 + e2) ^ ( (e2 ^ e1) + (e3 ^ e2) );

		//−e1 ∧ e2 ∧ e3
		assert(c(7) == -1);

		//c.print();
	}

	//Tests reffering to Scalar
	{
		// (e1 +e3 ) * ( e1 +e2 )
		Multivector e1 = Multivector(1);
		Multivector e2 = Multivector(2);
		Multivector e3 = Multivector(4);

		double c = (e1 + e3).sc(e1 + e2);

		//1
		assert(c == 1);		
	}

	//Testing left contraction
	{
		//e3 ⌋ (e1 +e2)
		Multivector e1 = Multivector(1);
		Multivector e2 = Multivector(2);
		Multivector e3 = Multivector(4);

		Multivector c = e3.lc(e1 + e2);

		//0
		assert(c(0) == 0);		
	}

	//Testing left contraction
	{
		//e3 ⌋ ((e1 +e3) ∧ (e1 +e2))
		Multivector e1 = Multivector(1);
		Multivector e2 = Multivector(2);
		Multivector e3 = Multivector(4);

		Multivector c = e3.lc( (e1 + e3) ^ (e1 + e2) );

		//e1 + e2
		//c.print();
		assert(c(1) == 1);
		assert(c(2) == 1);	
	}

	//Testing Left Contraction
	{
		//((e1 +e3) ∧ (e1 +e2)) ⌋ e1
		Multivector e1 = Multivector(1);
		Multivector e2 = Multivector(2);
		Multivector e3 = Multivector(4);

		Multivector c = ( (e1 + e3) ^ (e1 + e2) ).lc(e1);

		//0
		//c.print();
		assert(c(0) == 0);	
	}

	//Testing Scalar
	{
		//(2 (e1 +e3) + (e1 +e2)) ∗ ((e1 +e3) + (e1 +e2))
		Multivector e1 = Multivector(1);
		Multivector e2 = Multivector(2);
		Multivector e3 = Multivector(4);

		double c = (2*(e1 +e3) + (e1 +e2)).sc((e1 +e3) + (e1 +e2));

		//9
		//cout << c << endl;
		assert(c == 9);	
	}

	//Testing Right Contraction
	{
		//(e1 ∧ e2 ∧ e3) ⌊ (e1 + e2)
		Multivector e1 = Multivector(1);
		Multivector e2 = Multivector(2);
		Multivector e3 = Multivector(4);

		Multivector c = (e1 ^ e2 ^ e3).rc (e1 + e2);

		//−e1 ∧ e3 +e2 ∧ e3
		//c.print();
		assert(c(5) == -1);
		assert(c(6) == 1);
	}

	//Testing Regressive Product
	{

		Multivector a = Multivector();
		a(5) = 1;
		//a.print();
		Multivector b = Multivector();
		b(6) = -1;
		//b.print();
		int n = 3;
		Multivector c = a.rp(b, n);
		Multivector d = a ^ b;
		//c.print();
		//d.print();
	}

	//Testing Versors
	{
		Multivector a = Multivector();
		a(1) = 0.5;
		a(2) = 0.5;

		Multivector b = Multivector();
		b(1) = 1;

		Multivector c = a.gp(b).gp(a.inv());
		assert(c(2) = 1);
	}

	//Test Basis orthogonalization method
	{
		Multivector e1 = Multivector(1);
		Multivector e2 = Multivector(2);
		Multivector e3 = Multivector(4);

		vector<Multivector> basis;

		Multivector a = 0.5*e1 + 0.5*e2;
		basis.push_back(a);
		Multivector b = 0.5*e1 + 0.5*e3;
		basis.push_back(b);
		Multivector c = e3;
		basis.push_back(c);

		vector<Multivector> resp = _orthogonal_basis(basis);
		vector<Multivector>::iterator iter;
		for (iter = resp.begin(); iter != resp.end(); ++iter)
		{
			//(*iter).print();
		}

	}

	//Testing the Dual
	{
		Multivector e1 = Multivector(1);
		Multivector e2 = Multivector(2);

		Multivector c = (e1 ^ e2).dual(3);
		assert(c(4) == 1);
		//c.print();

		c = c.dual(3);
		assert(c(3) == -1);
	}

	//Testing the Dual
	{
		Multivector e1 = Multivector(1);
		Multivector e3 = Multivector(4);

		Multivector c = (e1 ^ e3).dual(3);
		assert(c(2) == -1);
		//c.print();

	}

	//Testing Meet and Join
	{
		Multivector a = Multivector();
		a(5) = 1;
		//a.print();
		Multivector b = Multivector();
		b(6) = -1;
		//b.print();

		Multivector c = a._meet(b,3);
		Multivector d = a._join(b,3);
		//c.print();
		//d.print();
	}

	//Testing Rotor
	{
		Multivector e1 = Multivector("1");
		Multivector e2 = Multivector("10");
		Multivector e3 = Multivector("100");
		Multivector R = rotor(e2 ^ e3, PI / 3);

		Multivector a = R.gp(e3).gp(R.rev());

		//a.print();
		assert(abs(a(2) + 0.866025) < 0.0001);
		assert(abs(a(4) -0.5) < 0.0001);
	}

	//Test reffering to outer product and the new initialization way
	{
		//(e1 +e2) ∧ (e2 ∧ e1 +e3 ∧ e2)
		Multivector e1 = Multivector("1");
		Multivector e2 = Multivector("10");
		Multivector e3 = Multivector("100");


		Multivector c = (e1 + e2) ^ ( (e2 ^ e1) + (e3 ^ e2) );

		//−e1 ∧ e2 ∧ e3
		assert(c(7) == -1);

		//c.print();
	}

	//Test reffering to Meet
	{
		//(e1 +e2) ∧ (e2 ∧ e1 +e3 ∧ e2)
		Multivector e1 = Multivector("1");
		Multivector e2 = Multivector("10");
		Multivector e3 = Multivector("100");


		Multivector c = (e1 + e2).meet ( (e2 ^ e1) + (e3 ^ e2),3 );

		assert(c(0) == -1);

		//c.print();
	}

	//Test reffering to Join
	{
		//(e1 +e2) ∧ (e2 ∧ e1 +e3 ∧ e2)
		Multivector e1 = Multivector("1");
		Multivector e2 = Multivector("10");
		Multivector e3 = Multivector("100");


		Multivector c = (e1 + e2).join ( (e2 ^ e1) + (e3 ^ e2),3 );

		assert(c("111") == 1);

		//c.print();
	}

	//Testing Rotor
	{
		Multivector e1 = Multivector("1");
		Multivector e3 = Multivector("100");
		Multivector e4 = Multivector("1000");
		Multivector R = rotor(e1 ^ e3, PI / 2);

		Multivector a = R.gp(e1 ^ e4).gp(R.rev());

		//a.print();
		assert(a("1100") == 1);
	}

	//Testing solving linear equation
	{
		Multivector e1 = Multivector("1");
		Multivector e2 = Multivector("10");
		Multivector e3 = Multivector("100");
		Multivector f1 = 2*e1 - 3*e2;
		Multivector f2 = e1 - 2*e2 + 3*e3;

		Multivector res = (f1^f2).undual(3);

		res.print();
		//assert(a("1100") == 1);
	}

	{
		Multivector o   = Multivector("1");
		Multivector e1  = Multivector("10");
		Multivector e2  = Multivector("100");
		Multivector e3  = Multivector("1000");
		Multivector inf = Multivector("10000");

		mat space;
		space << 0  << 0 << 0 << 0 << -1 << endr
			  << 0  << 1 << 0 << 0 << 0  << endr
			  << 0  << 0 << 1 << 0 << 0  << endr
			  << 0  << 0 << 0 << 1 << 0  << endr
			  << -1 << 0 << 0 << 0 << 0  << endr;


		Multivector a = 8*e1 ^ e2;
		Multivector b = 9*e2;
		Multivector c = ggp(a,b,space);
		c.print();

	}

	{
		Multivector e1 = Multivector("1");
		Multivector e2 = Multivector("10");
		Multivector e3 = Multivector("100");

		mat space;
		space << 1  << 0 << 0 << endr
			  << 0  << 1 << 0 << endr
			  << 0  << 0 << -1 << endr;

		Multivector c = ggp(e3, e1 ^ e2 ^ e3,space);
		c.print();
	}

	{
		Multivector o   = Multivector("1");
		Multivector e1  = Multivector("10");
		Multivector e2  = Multivector("100");
		Multivector e3  = Multivector("1000");
		Multivector inf = Multivector("10000");

		mat space;
		space << 0  << 0 << 0 << 0 << -1 << endr
			  << 0  << 1 << 0 << 0 << 0  << endr
			  << 0  << 0 << 1 << 0 << 0  << endr
			  << 0  << 0 << 0 << 1 << 0  << endr
			  << -1 << 0 << 0 << 0 << 0  << endr;


		Multivector a = o ^ inf;
		Multivector b = inf;
		Multivector c = ggp(a,b,space);
		//Multivector c = a.gp(b);
		c.print();

	}

}



